Skip to content

wp-mixer, tray: fix two SIGSEGV crashes from missing null checks#423

Open
borisi1 wants to merge 2 commits intoWayfireWM:masterfrom
borisi1:fix/wp-mixer-on-mixer-changed-uninit-control
Open

wp-mixer, tray: fix two SIGSEGV crashes from missing null checks#423
borisi1 wants to merge 2 commits intoWayfireWM:masterfrom
borisi1:fix/wp-mixer-on-mixer-changed-uninit-control

Conversation

@borisi1
Copy link
Copy Markdown

@borisi1 borisi1 commented Apr 21, 2026

Fixes two independent SIGSEGV crashes


1. wp-mixer: uninitialized control pointer in on_mixer_changed

Crash address: 0xffffffffffffffe8 (-0x18 — method call on null/freed object)

Stack trace:

#0  Gtk::ToggleButton::set_active(bool)  [libgtkmm-4.0.so.0]
#1  <wf-panel + 0xc3257>
#2  g_signal_emit  [libgobject-2.0.so.0]
#3  libwireplumber-module-mixer-api.so

Root cause: control is declared uninitialized. Two bugs in the search loop:

  1. If objects_to_controls is empty (e.g. during startup or after restart), the loop body never executes and control remains uninitialized — execution continues and calls control->set_btn_status_no_callbk() on garbage.
  2. The end-of-loop check dereferences map::end() (UB). In a range-for loop the iterator never equals end(), so if no matching ID is found the loop exits with control pointing to the last element (wrong object).

Fix: Initialize control to nullptr, remove the broken end() dereference, and use a post-loop null check. Changed return to continue so remaining widgets still get updated.


2. tray: null GVariant crash in on_bus_acquired

Stack trace:

#0  g_bit_lock_and_get       [libglib-2.0.so.0]
#1  g_variant_n_children     [libglib-2.0.so.0]
#2  Glib::Variant<std::vector<Glib::ustring>>::get()  [libglibmm-2.68.so.1]
#3  StatusNotifierHost::on_bus_acquired lambda  [wf-panel]

Root cause: get_cached_property may leave the variant uninitialized if RegisteredStatusNotifierItems is not yet in the D-Bus proxy cache (common on fast restart before the watcher proxy has fully synced). Calling .get() on a null Glib::Variant calls g_variant_n_children(nullptr) → SIGSEGV.

Fix: Guard the loop with a null check on the variant before calling .get().


Tested on

  • CachyOS (Arch-based), kernel 7.0.0-1-cachyos
  • wf-shell r464.f926b19, WirePlumber 0.5.14, PipeWire 1.6.3
  • Wayfire (Wayland), dual monitor setup
  • Both crashes reproduced and confirmed fixed with patched binary

borisi1 added 2 commits April 21, 2026 10:50
The loop searching objects_to_controls for a matching PipeWire ID
left 'control' uninitialized when the map was empty, and used
end()->first (UB) as a termination check when no match was found.
Both cases allowed execution to continue with a garbage pointer,
leading to a SIGSEGV in Gtk::ToggleButton::set_active().

Initialize control to nullptr, drop the broken end() dereference,
and use a post-loop null check with continue instead of return so
other widgets are still updated.
get_cached_property may leave the variant uninitialized if the
property is not yet in the D-Bus proxy cache (e.g. on fast restart
before the watcher proxy has fully synced). Calling .get() on a
null Glib::Variant calls g_variant_n_children(nullptr) -> SIGSEGV.

Guard the loop with a null check on the variant.
@borisi1 borisi1 changed the title wp-mixer: fix uninitialized control pointer crash in on_mixer_changed wp-mixer, tray: fix two SIGSEGV crashes from missing null checks Apr 21, 2026
Copy link
Copy Markdown
Collaborator

@trigg trigg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good, clear explanation.

Tentative approval and I plan to compile and test soon.

Thanks for the contribution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants